#pragma once
#include <iostream>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

// Tcpsever提供对Connection的管理工作
class Reacotr
{
    static const int N = 64;

public:
    Reacotr()
        : _isrunning(false)
    {
    }
    bool IsExistInConnections(int fd)
    {
        auto pos = _connections.find(fd);
        if (pos != _connections.end())
            return true;
        return false;
    }
    // 把传进来的fd啥的，用Epoller封装成Connection
    void AddConnection(int fd, uint32_t events, func_t recv, func_t send = nullptr, func_t except = nullptr)
    {
        // 1.先添加listenfd
        Connection *conn = new Connection(fd);
        conn->SetEvent(events);
        conn->SetFunc(recv, send, except);
        conn->SetSelf(this);

        // 2.对添加到conn进行管理
        _epoller.AddEvents(conn->Sockfd(), conn->GetEvent());

        // 3.把conn加入unordered_map
        _connections.insert(make_pair(conn->Sockfd(), conn));
    }

    void EnableReadWrite(int sockfd, bool read, bool write)
    {
        uint32_t events = (read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0) | EPOLLET;
        if (IsExistInConnections(sockfd))
        {
            // 1.改_connections管理的所关心的事件
            _connections[sockfd]->SetEvent(events);
            // 2.写透到内核
            _epoller.ModEvents(sockfd, events);
        }
    }
    void RemoveConnection(int fd)
    {
        if (!IsExistInConnections(fd))
            return;
        // 1.关闭epoll的关心
        _epoller.DelEvents(fd);
        // 2.关闭服务器端的fd连接,反正connection连接包含了它自己的fd，所以让成员函数关fd
        _connections[fd]->Close();
        // 3.删除connection连接对象，清理_connections结构的KV对儿
        delete _connections[fd];
        _connections.erase(fd);
    }
    void List()
    {
        cout << "————————————————————————————" << endl;
        for (auto &connection : _connections)
        {
            cout << "fd: " << connection.second->Sockfd() << ",";
            uint32_t events = connection.second->GetEvent();
            if (events & (EPOLLIN | EPOLLET))
            {
                cout << "EPOLLIN | EPOLLET" << endl;
            }
            if (events & (EPOLLOUT | EPOLLET))
            {
                cout << "EPOLLOUT | EPOLLET" << endl;
            }
        }
        cout << "————————————————————————————" << endl;
    }
    // 事件派发核心函数
    void dispatcher()
    {
        _isrunning = true;
        int timeout = 3000;
        while (_isrunning)
        {
            LoopOnce(timeout);
            // 干其他事情
            List();
        }
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller.Wait(_epvs, N, timeout);

        for (int i = 0; i < n; i++)
        {
            uint32_t event = _epvs[i].events;
            int sockfd = _epvs[i].data.fd;
            // 把其他错误转为读写错误
            if (event & EPOLLHUP)
                event |= (EPOLLIN | EPOLLOUT);
            if (event & EPOLLERR)
                event |= (EPOLLIN | EPOLLOUT);
            // 如果在读时出错，OS把sockfd删除了，那后面就会报错，所以每次都需要判断一下连接是否存在
            if (event & EPOLLIN)
            {
                if (IsExistInConnections(sockfd) && (_connections[sockfd]->_recver != nullptr))
                    _connections[sockfd]->_recver(_connections[sockfd]); // 别忘了他是个包装器
            }
            if (event & EPOLLOUT)
            {
                if (IsExistInConnections(sockfd) && (_connections[sockfd]->_sender != nullptr))
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~Reacotr()
    {
    }

private:
    unordered_map<int, Connection *> _connections;
    Epoller _epoller;
    struct epoll_event _epvs[N];
    bool _isrunning;
};